home *** CD-ROM | disk | FTP | other *** search
/ Acorn User: China / Acorn User China CD-ROM (UK) (Disc A) / Acorn User China CD-ROM (UK) (Disc A).bin / DEMON / DEVELOPER / HYPERMAIL.ARC / !hypermail_c_parse < prev    next >
Encoding:
Text File  |  1996-01-24  |  25.1 KB  |  754 lines

  1. /*
  2. ** Copyright (C) 1994, Enterprise Integration Technologies Corp.        
  3. ** All Rights Reserved.
  4. ** Kevin Hughes, kevinh@eit.com 
  5. ** 7/31/94
  6. */
  7.  
  8. #include "hypermail.h"
  9. #include "parse.h"
  10.  
  11. /* Parsing...the heart of Hypermail!
  12. ** This loads in the articles from stdin or a mailbox, adding the right
  13. ** field variables to the right structures. If readone is set, it will
  14. ** think anything it reads in is one article only.
  15. */
  16.  
  17. void loadheaders(mbox, use_stdin, readone)
  18.      char *mbox;
  19.      int use_stdin;
  20.      int readone;
  21. {
  22.         FILE *fp;
  23.         char name[NAMESTRLEN], email[MAILSTRLEN], date[DATESTRLEN],
  24.                 msgid[MSGDSTRLEN], subject[SUBJSTRLEN], inreply[REPYSTRLEN],
  25.                 line[MAXLINE], tmpfrom[MAXLINE], fromdate[DATESTRLEN],
  26.                 oldline[MAXLINE];
  27.         int num, isinheader, hassubject, hasdate, wasinreply;
  28.         struct body *bp;
  29.  
  30.         if (!strcmp(mbox, "NONE") || use_stdin)
  31.                 fp = stdin;
  32.         else {
  33.                 if ((fp = fopen(mbox, "r")) == NULL) {
  34.                         sprintf(errmsg, "Couldn't open mail archive \"%s\".",
  35.                         mbox);
  36.                         progerr(NULL);
  37.                 }
  38.         }
  39.  
  40.         if (readone)
  41.                 num = bignum;
  42.         else
  43.                 num = 0;
  44.         hassubject = 0;
  45.         hasdate = 0;
  46.         wasinreply = 0;
  47.         isinheader = 1;
  48.         inreply[0] = '\0';
  49.         tmpfrom[0] = '\0';
  50.         oldline[0] = '\0';
  51.         bp = NULL;
  52.         if (!readone) {
  53.                 replylist = NULL;
  54.                 subjectlist = NULL;
  55.                 authorlist = NULL;
  56.                 datelist = NULL;
  57.         }
  58.         if (showprogress && readone)
  59.                 printf("Reading new header...\n");
  60.         if (showprogress && !readone) {
  61.                 if (!strcmp(mbox, "NONE") || use_stdin)
  62.                         printf("Loading mailbox...    ");
  63.                 else
  64.                         printf("Loading mailbox \"%s\"...    ", mbox);
  65.         }
  66.         while (fgets(line, MAXLINE, fp) != NULL) {
  67.                 if (isinheader) {
  68.                         if (!strncmp(line, "Received:", 9) ||
  69.                         !strncmp(line, "Return-Path:", 12) ||
  70.                         !strncmp(line, "Cc:", 3) ||
  71.                         !strncmp(line, "X-", 2) ||
  72.                         !strncmp(line, "Flags:", 6))
  73.                                 continue;
  74.                         if (!strncmp(line, "From ", 5))
  75.                                 strcpy(fromdate, (char *) getfromdate(line));
  76.                         else if (!strncmp(line, "Date:", 5)) {
  77.                                 bp = (struct body *) addbody(bp, line);
  78.                                 strcpy(date, (char *) getmaildate(line));
  79.                                 hasdate = 1;
  80.                         }
  81.                         else if (!strncmp(line, "From:", 5)) {
  82.                                 bp = (struct body *) addbody(bp, line);
  83.                                 getname(line, name, email);
  84.                         }
  85.                         else if (!strncmp(line, "Message-Id:", 11)) {
  86.                                 bp = (struct body *) addbody(bp, line);
  87.                                 strcpy(msgid, (char *) getid(line));
  88.                         }
  89.                         else if (!strncmp(line, "Subject:", 8)) {
  90.                                 bp = (struct body *) addbody(bp, line);
  91.                                 strcpy(subject, (char *) getsubject(line));
  92.                                 hassubject = 1;
  93.                         }
  94.                         else if (!strncmp(line, "In-Reply-To:", 12)) {
  95.                                 bp = (struct body *) addbody(bp, line);
  96.                                 strcpy(inreply, (char *) getreply(line));
  97.                                 wasinreply = 1;
  98.                         }
  99.                         else if ((!strncmp(line, "    ", 4) ||
  100.                         line[0] == '\t') &&
  101.                         strchr(line, '<') && strchr(line, '>') &&
  102.                         strchr(line, '@') && wasinreply) {
  103.                                 bp = (struct body *) addbody(bp, line);
  104.                                 strcpy(inreply, (char *) getreply(line));
  105.                                 wasinreply = 0;
  106.                         }
  107.                         else if (!strncmp(line, "To:", 3))
  108.                                 bp = (struct body *) addbody(bp, line);
  109.                         else if (line[0] == '\n') {
  110.                                 bp = (struct body *) addbody(bp, line);
  111.                                 isinheader = 0;
  112.                         }
  113.                 }
  114.                 else {
  115.                         if (!strncmp(line, "From ", 5)) {
  116.                                 if (readone)
  117.                                         continue;
  118.                                 if (strstr(oldline,
  119.                                 "Forwarded message:")) {
  120.                                         oldline[0] = '\0';
  121.                                         continue;
  122.                                 }
  123.                                 isinheader = 1;
  124.                                 wasinreply = 0;
  125.                                 if (!hassubject)
  126.                                         strcpy(subject, NOSUBJECT);
  127.                                 else
  128.                                         hassubject = 1;
  129.                                 if (!hasdate)
  130.                                         strcpy(date, NODATE);
  131.                                 else
  132.                                         hasdate = 1;
  133.                                 if (inreply[0] == '\0')
  134.                                         oneunre(inreply, subject);
  135.                                 while (rmlastlines(bp));
  136.                                 addhash(num, date, name, email, msgid, subject,
  137.                                 inreply, fromdate, bp);
  138.                                 authorlist = (struct header *)
  139.                                 addheader(authorlist, num, name, subject,
  140.                                 date, 1);
  141.                                 subjectlist = (struct header *)
  142.                                 addheader(subjectlist, num, name, unre(subject),
  143.                                 date, 0);
  144.                                 datelist = (struct header *)
  145.                                 addheader(datelist, num, name, subject,
  146.                                 fromdate, 2);
  147.                                 strcpy(fromdate, (char *) getfromdate(line));
  148.  
  149.                                 bp = NULL;
  150.                                 num++;
  151.  
  152.                                 if (!(num % 10) && showprogress && !readone) {
  153.  
  154. #ifdef RISCOS
  155.                                         printf("%4d,", num);
  156. #else
  157.                                         printf("\b\b\b\b%4d", num);
  158. #endif
  159.                                         fflush(stdout);
  160.                                 }
  161.                                 inreply[0] = '\0';
  162.                         }
  163.                         else
  164.                                 bp = (struct body *) addbody(bp, line);
  165.                 }
  166.                 strcpy(oldline, line);
  167.         }
  168.         if (!isinheader) {
  169.                 if (!hassubject)
  170.                         strcpy(subject, NOSUBJECT);
  171.                 if (!hasdate)
  172.                         strcpy(date, NODATE);
  173.                 if (inreply[0] == '\0')
  174.                         oneunre(inreply, subject);
  175.                 while (rmlastlines(bp));
  176.                 addhash(num, date, name, email, msgid, subject, inreply,
  177.                 fromdate, bp);
  178.                 authorlist = (struct header *)
  179.                 addheader(authorlist, num, name, subject, date, 1);
  180.                 subjectlist = (struct header *)
  181.                 addheader(subjectlist, num, name, unre(subject), date, 0);
  182.                 datelist = (struct header *) addheader(datelist, num, name,
  183.                 subject, fromdate, 2);
  184.                 num++;
  185.         }
  186.         if (showprogress && !readone)
  187.  
  188. #ifdef RISCOS
  189.                 printf("%4d articles.\n", num);
  190. #else
  191.                 printf("\b\b\b\b%4d articles.\n", num);
  192. #endif
  193.  
  194.         if (!readone)
  195.                 bignum = num - 1;
  196.         fclose(fp);
  197.  
  198.         crossindex();
  199.  
  200.         threadlist = NULL;
  201.         printedthreadlist = NULL;
  202.         crossindexthread1(datelist);
  203. }
  204.  
  205. /* All this does is get all the relevant header information from the
  206. ** comment fields in existing archive files. Everything is loaded into
  207. ** structures in the exact same way as if articles were being read from
  208. ** stdin or a mailbox.
  209. */
  210.  
  211. void loadoldheaders(dir)
  212.      char *dir;
  213. {
  214.         FILE *fp;
  215.         char name[NAMESTRLEN], email[MAILSTRLEN], date[DATESTRLEN],
  216.                 msgid[MSGDSTRLEN], subject[SUBJSTRLEN], inreply[REPYSTRLEN],
  217.                 line[MAXLINE], fromdate[DATESTRLEN], filename[MAXFILELEN];
  218.         int num;
  219.         struct body *bp;
  220.  
  221.         num = 0;
  222.         sprintf(filename, "%s%s%.4d.html", dir,
  223.         (dir[strlen(dir) - 1] == '/') ? "" : "/", num);
  224.  
  225.         bp = NULL;
  226.         bp = (struct body *) addbody(bp, "\0");
  227.  
  228.         authorlist = subjectlist = datelist = NULL;
  229.  
  230.         if (showprogress)
  231.                 printf("Reading old headers...    ");
  232.         while ((fp = fopen(filename, "r")) != NULL) {
  233.  
  234.                 fgets(line, MAXLINE, fp);
  235.                 strcpy(fromdate, (char *) getvalue(line));
  236.                 fgets(line, MAXLINE, fp);
  237.                 strcpy(date, (char *) getvalue(line));
  238.                 fgets(line, MAXLINE, fp);
  239.                 strcpy(name, (char *) getvalue(line));
  240.                 fgets(line, MAXLINE, fp);
  241.                 strcpy(email, (char *) getvalue(line));
  242.                 fgets(line, MAXLINE, fp);
  243.                 strcpy(subject, (char *) unconvchars(getvalue(line)));
  244.                 fgets(line, MAXLINE, fp);
  245.                 strcpy(msgid, (char *) getvalue(line));
  246.                 fgets(line, MAXLINE, fp);
  247.                 strcpy(inreply, (char *) unconvchars(getvalue(line)));
  248.  
  249.                 fclose(fp);
  250.  
  251.                 addhash(num, date, name, email, msgid, subject,
  252.                 inreply, fromdate, bp);
  253.                 authorlist = (struct header *)
  254.                 addheader(authorlist, num, name, subject, date, 1);
  255.                 subjectlist = (struct header *)
  256.                 addheader(subjectlist, num, name, unre(subject), date, 0);
  257.                 datelist = (struct header *)
  258.                 addheader(datelist, num, name, subject, fromdate, 2);
  259.  
  260.                 num++;
  261.                 if (!(num % 10) && showprogress) {
  262.  
  263. #ifdef RISCOS
  264.                         printf("%4d", num);
  265. #else
  266.                         printf("\b\b\b\b%4d", num);
  267. #endif
  268.                         fflush(stdout);
  269.                 }
  270.  
  271.                 sprintf(filename, "%s%s%.4d.html", dir,
  272.                 (dir[strlen(dir) - 1] == '/') ? "" : "/", num);
  273.         }
  274.         if (showprogress)
  275.  
  276. #ifdef RISCOS
  277.                 printf("%4d articles.\n", num);
  278. #else
  279.                 printf("\b\b\b\b%4d articles.\n", num);
  280. #endif
  281.  
  282.         if (!num)
  283.                 bignum = 0;
  284.         else
  285.                 bignum = num;
  286. }
  287.  
  288. /* Adds a "Next:" link in the proper article, after the archive has been
  289. ** incrementally updated.
  290. */
  291.  
  292. void fixnextheader(dir, num)
  293.      char *dir;
  294.      int num;
  295. {
  296.         char filename[MAXFILELEN], line[MAXLINE], name[NAMESTRLEN],
  297.                 email[MAILSTRLEN], subject[SUBJSTRLEN], inreply[REPYSTRLEN],
  298.                 date[DATESTRLEN], fromdate[DATESTRLEN], msgid[MSGDSTRLEN];
  299.         struct body *bp, *status;
  300.         FILE *fp;
  301.  
  302.         sprintf(filename, "%s%s%.4d.html", dir,
  303.         (dir[strlen(dir) - 1] == '/') ? "" : "/", num);
  304.  
  305.         bp = NULL;
  306.         if ((fp = fopen(filename, "r")) != NULL) {
  307.                 while ((fgets(line, MAXLINE, fp)) != NULL)
  308.                         bp = (struct body *) addbody(bp, line);
  309.         }
  310.         else
  311.                 return;
  312.         fclose(fp);
  313.  
  314.         if ((fp = fopen(filename, "w+")) != NULL)
  315.                 while (bp != NULL) {
  316.                         fprintf(fp, "%s", bp->line);
  317.                         if (!strncmp(bp->line, "<!-- next=", 10)) {
  318.  
  319.                                 status = (struct body *) hashnumlookup(num + 1,
  320.                                 name, email, subject, inreply, date, fromdate,
  321.                                 msgid);
  322.                                 if (status != NULL) {
  323.                                 fprintf(fp, "<li> <b>Next message:</b> ");
  324.                                 fprintf(fp,
  325.                                 "<a href=\"%.4d.html\">%s: \"%s\"</a>\n",
  326.                                 num + 1, name, convchars(subject));
  327.                                 }
  328.  
  329.                         }
  330.                         bp = bp->next;
  331.                 }
  332.         fclose(fp);
  333. }
  334.  
  335. /* Adds a "Reply:" link in the proper article, after the archive has been
  336. ** incrementally updated.
  337. */
  338.  
  339. void fixreplyheader(dir, num)
  340.      char *dir;
  341.      int num;
  342. {
  343.         int replynum, subjmatch;
  344.         char filename[MAXFILELEN], line[MAXLINE], name[NAMESTRLEN],
  345.                 email[MAILSTRLEN], subject[SUBJSTRLEN], inreply[REPYSTRLEN],
  346.                 date[DATESTRLEN], fromdate[DATESTRLEN], msgid[MSGDSTRLEN],
  347.                 name2[NAMESTRLEN], subject2[SUBJSTRLEN];
  348.         struct body *bp, *status;
  349.         FILE *fp;
  350.  
  351.         status = (struct body *) hashnumlookup(num,
  352.         name, email, subject, inreply, date, fromdate, msgid);
  353.         if (status == NULL || inreply[0] == '\0')
  354.                 return;
  355.         if (inreply[0] != '\0') {
  356.                 replynum = hashreplylookup(inreply, name2, subject2,
  357.                 &subjmatch);
  358.                 if (replynum == -1)
  359.                         return;
  360.         }
  361.  
  362.         sprintf(filename, "%s%s%.4d.html", dir,
  363.         (dir[strlen(dir) - 1] == '/') ? "" : "/", replynum);
  364.  
  365.         bp = NULL;
  366.         if ((fp = fopen(filename, "r")) != NULL) {
  367.                 while ((fgets(line, MAXLINE, fp)) != NULL)
  368.                         bp = (struct body *) addbody(bp, line);
  369.         }
  370.         else
  371.                 return;
  372.         fclose(fp);
  373.  
  374.         if ((fp = fopen(filename, "w+")) != NULL)
  375.                 while (bp != NULL) {
  376.                         if (!strncmp(bp->line, "<!-- reply", 10)) {
  377.                                 fprintf(fp, "<li> <b>Reply:</b> ");
  378.                                 fprintf(fp, "<a href=\"%.4d.html\">", num);
  379.                                 fprintf(fp, "%s: \"%s\"</a>\n",
  380.                                 name, convchars(subject));
  381.                         }
  382.                         fprintf(fp, "%s", bp->line);
  383.                         bp = bp->next;
  384.                 }
  385.         fclose(fp);
  386. }
  387.  
  388. /* Adds a "Next in thread:" link in the proper article, after the archive
  389. ** has been incrementally updated.
  390. */
  391.  
  392. void fixthreadheader(dir, num)
  393.      char *dir;
  394.      int num;
  395. {
  396.         int threadnum;
  397.         char filename[MAXFILELEN], line[MAXLINE], name[NAMESTRLEN],
  398.                 subject[SUBJSTRLEN];
  399.         struct body *bp;
  400.         struct reply *rp;
  401.         FILE *fp;
  402.  
  403.         for (rp = threadlist; rp != NULL; rp = rp->next)
  404.                 if (rp->next != NULL && rp->next->msgnum == num &&
  405.                 rp->msgnum != -1) {
  406.                         threadnum = rp->msgnum;
  407.                         strcpy(name, rp->next->name);
  408.                         strcpy(subject, rp->next->subject);
  409.                         break;
  410.                 }
  411.         if (rp == NULL)
  412.                 return;
  413.  
  414.         sprintf(filename, "%s%s%.4d.html", dir,
  415.         (dir[strlen(dir) - 1] == '/') ? "" : "/", threadnum);
  416.  
  417.         bp = NULL;
  418.         if ((fp = fopen(filename, "r")) != NULL) {
  419.                 while ((fgets(line, MAXLINE, fp)) != NULL)
  420.                         bp = (struct body *) addbody(bp, line);
  421.         }
  422.         else
  423.                 return;
  424.         fclose(fp);
  425.  
  426.         if ((fp = fopen(filename, "w+")) != NULL)
  427.                 while (bp != NULL) {
  428.                         fprintf(fp, "%s", bp->line);
  429.                         if (!strncmp(bp->line, "<!-- nextthr", 12)) {
  430.                                 fprintf(fp, "<li> <b>Next in thread:</b> ");
  431.  
  432. #ifdef RISCOS
  433.  
  434.                                 fprintf(fp, "<a href=\"file://%s/%s/%.4d/%.4d\">",
  435.                                 HOST, FILEDIR, num/FPD, num);
  436.                                 fprintf(fp, "%s: \"%s\"</a>\n",
  437.                                 name, convchars(subject));
  438.  
  439. #else
  440.                                 fprintf(fp, "<a href=\"%.4d.html\">", num);
  441.                                 fprintf(fp, "%s: \"%s\"</a>\n",
  442.                                 name, convchars(subject));
  443. #endif
  444.  
  445.                         }
  446.                         bp = bp->next;
  447.                 }
  448.         fclose(fp);
  449. }
  450.  
  451. /* Cross-indexes - adds to a list of replies. If a message is a reply to
  452. ** another, the number of the messge it's replying to is added to the list.
  453. ** This list is searched upon printing.
  454. */
  455.  
  456. void crossindex()
  457. {
  458.         int num, status, maybereply;
  459.         char name[NAMESTRLEN], subject[SUBJSTRLEN], email[MAILSTRLEN],
  460.                 inreply[REPYSTRLEN], date[DATESTRLEN], fromdate[DATESTRLEN],
  461.                 msgid[MSGDSTRLEN];
  462.  
  463.         num = 0;
  464.         replylist = NULL;
  465.  
  466.         while (hashnumlookup(num, name, email, subject, inreply,
  467.         date, fromdate, msgid) != NULL) {
  468.                 if (inreply[0] != '\0') {
  469.                         status = hashreplynumlookup(inreply, &maybereply);
  470.                         if (status != -1)
  471.                                 replylist = (struct reply *)
  472.                                 addreply(replylist, status, num, name, subject,
  473.                                 maybereply);
  474.                 }
  475.                 num++;
  476.         }
  477. }
  478.  
  479. /* First, print out the threads in order by date...
  480. ** Each message number is appended to a thread list. Threads and individual
  481. ** messages are separated by a -1.
  482. */
  483.  
  484. void crossindexthread1(hp)
  485.      struct header *hp;
  486. {
  487.         int hasreply;
  488.         struct reply *rp;
  489.  
  490.         if (hp != NULL) {
  491.                 crossindexthread1(hp->left);
  492.  
  493.                 for (hasreply = 0, rp = replylist; rp != NULL; rp = rp->next)
  494.                         if (rp->frommsgnum == hp->msgnum) {
  495.                                 hasreply = 1;
  496.                                 break;
  497.                         }
  498.  
  499.                 if (!hasreply && !wasprinted(printedthreadlist, hp->msgnum)) {
  500.                         threadlist = (struct reply *)
  501.                         addreply(threadlist, hp->msgnum, hp->msgnum,
  502.                         hp->name, hp->subject, 0);
  503.                         crossindexthread2(hp->msgnum);
  504.                         threadlist = (struct reply *)
  505.                         addreply(threadlist, -1, -1, " ", " ", 0);
  506.                 }
  507.  
  508.                 crossindexthread1(hp->right);
  509.         }
  510. }
  511.  
  512. /* Recursively checks for replies to replies to a message, etc.
  513. ** Replies are added to the thread list.
  514. */
  515.  
  516. void crossindexthread2(num)
  517.      int num;
  518. {
  519.         struct reply *rp;
  520.  
  521.         for (rp = replylist; rp != NULL; rp = rp->next)
  522.                 if (rp->msgnum == num) {
  523.                         threadlist = (struct reply *)
  524.                         addreply(threadlist, rp->frommsgnum, num,
  525.                         rp->name, rp->subject, 0);
  526.                         printedlist = (struct printed *)
  527.                         markasprinted(printedthreadlist, rp->frommsgnum);
  528.                         crossindexthread2(rp->frommsgnum);
  529.                 }
  530. }
  531.  
  532. /* Grabs the date string from a Date: header.
  533. */
  534.  
  535. char *getmaildate(line)
  536.      char *line;
  537. {
  538.         int i;
  539.         char *c;
  540.         static char date[DATESTRLEN];
  541.  
  542.         c = (char *) strchr(line, ':');
  543.         if ((*(c + 1) && *(c + 1) == '\n') ||
  544.         (*(c + 2) && *(c + 2) == '\n')) {
  545.                 strcpy(date, NODATE);
  546.                 return date;
  547.         }
  548.         c += 2;
  549.         while (isspace(*c))
  550.                 c++;
  551.         for (i = 0; *c && *c != '\n' && i < DATESTRLEN; c++)
  552.                 date[i++] = *c;
  553.         date[i] = '\0';
  554.  
  555.         return date;
  556. }
  557.  
  558. /* Grabs the date string from a From article separator.
  559. */
  560.  
  561. char *getfromdate(line)
  562.      char *line;
  563. {
  564.         int i;
  565.         char *c;
  566.         static char tmpdate[DATESTRLEN];
  567.  
  568.         for (i = 0; days[i] != NULL && (c = (char *) strstr(line, days[i]))
  569.         == NULL; i++)
  570.                 ;
  571.         if (days[i] == NULL)
  572.                 tmpdate[0] = '\0';
  573.         else {
  574.                 for (i = 0; *c && *c != '\n' && i < DATESTRLEN; c++)
  575.                         tmpdate[i++] = *c;
  576.                 tmpdate[i] = '\0';
  577.                 if (tmpdate[16] != ':') {
  578.                         tmpdate[16] = ':';
  579.                         tmpdate[17] = '0';
  580.                         tmpdate[18] = '0';
  581.                         tmpdate[19] = ' ';
  582.                         tmpdate[20] = thisyear[0];
  583.                         tmpdate[21] = thisyear[1];
  584.                         tmpdate[22] = thisyear[2];
  585.                         tmpdate[23] = thisyear[3];
  586.                         tmpdate[24] = '\0';
  587.                 }
  588.                 sprintf(tmpdate, "%s %s", tmpdate, timezonestr);
  589.                 return tmpdate;
  590.         }
  591.  
  592.         return tmpdate;
  593. }
  594.  
  595. /* Grabs the name and email address from a From: header.
  596. ** This could get tricky; I've tried to keep it simple.
  597. */
  598.  
  599. void getname(line, name, email)
  600.      char *line;
  601.      char *name;
  602.      char *email;
  603. {
  604.         int i;
  605.         char *c;
  606.  
  607.         if ((c = (char *) strchr(line, '@')) == NULL) {
  608.                 if (strchr(line, '(')) {
  609.                         c = (char *) strchr(line, ':') + 1;
  610.                         while (isspace(*c))
  611.                                 c++;
  612.                         for (i = 0; *c && *c != '(' && *c != ' ' &&
  613.                         *c != '\n' && i < MAILSTRLEN; c++)
  614.                                 email[i++] = *c;
  615.                         email[i] = '\0';
  616.                 }
  617.                 else
  618.                         strcpy(email, NOEMAIL);
  619.         }
  620.         else {
  621.                 while (*c != ' ' && *c != '<')
  622.                         c--;
  623.                 c++;
  624.                 for (i = 0; *c && *c != '>' && *c != ' ' && *c != '\n' &&
  625.                 i < MAILSTRLEN;
  626.                 c++)
  627.                         email[i++] = *c;
  628.                 email[i] = '\0';
  629.         }
  630.  
  631.         if (strchr(line, '<')) {
  632.                 c = (char *) strchr(line, ':') + 1;
  633.                 while (isspace(*c) || *c == '\"')
  634.                         c++;
  635.         }
  636.         else if (strchr(line, '('))
  637.                 c = (char *) strchr(line, '(') + 1;
  638.         else {
  639.                 if (strcmp(email, NOEMAIL))
  640.                         strcpy(name, email);
  641.                 else
  642.                         strcpy(name, NONAME);
  643.                 return;
  644.         }
  645.  
  646.         for (i = 0; *c && *c != '<' && *c != '\"' && *c != ')' &&
  647.         *c != '(' && *c != '\n' && i < NAMESTRLEN; c++)
  648.                 name[i++] = *c;
  649.         if (*c == '<' || *c == '(')
  650.                 name[--i] = '\0';
  651.         else
  652.                 name[i] = '\0';
  653. }
  654.  
  655. /* Grabs the message ID, like <...> from the Message-ID: header.
  656. */
  657.  
  658. char *getid(line)
  659.      char *line;
  660. {
  661.         int i;
  662.         char *c;
  663.         static char msgid[MSGDSTRLEN];
  664.  
  665.         c = (char *) strchr(line, '<') + 1;
  666.         for (i = 0; *c && *c != '>' && *c != '\n' && i < MSGDSTRLEN; c++) {
  667.                 if (*c == '\\')
  668.                         continue;
  669.                 msgid[i++] = *c;
  670.         }
  671.         msgid[i] = '\0';
  672.  
  673.         return msgid;
  674. }
  675.  
  676. /* Grabs the subject from the Subject: header.
  677. */
  678.  
  679. char *getsubject(line)
  680.      char *line;
  681. {
  682.         int i;
  683.         char *c;
  684.         static char subject[SUBJSTRLEN];
  685.  
  686.         c = (char *) strchr(line, ':') + 2;
  687.         while (isspace(*c))
  688.                 c++;
  689.         for (i = 0; *c && *c != '\n' && i < SUBJSTRLEN; c++)
  690.                 subject[i++] = *c;
  691.         subject[i] = '\0';
  692.         for (i--; i >= 0 && isspace(subject[i]); i--)
  693.                 subject[i] = '\0';
  694.  
  695.         if (subject[0] == NULL || isspace(subject[0]) || subject[0] == '\n' ||
  696. #ifdef RISCOS
  697.         !strcmp(subject, "Re:"))
  698. #else
  699.         !strcasecmp(subject, "Re:"))
  700. #endif
  701.                 strcpy(subject, NOSUBJECT);
  702.  
  703.         return subject;
  704. }
  705.  
  706. /* Grabs the message ID, or date, from the In-reply-to: header.
  707. ** Who knows what other formats are out there...
  708. */
  709.  
  710. char *getreply(line)
  711.      char *line;
  712. {
  713.         int i;
  714.         char *c;
  715.         static char reply[REPYSTRLEN];
  716.  
  717.         if ((c = (char *) strstr(line, "dated: ")) != NULL) {
  718.                 c += 7;
  719.                 for (i = 0; *c && *c != '.' && *c != '\n' && i < REPYSTRLEN;
  720.                 c++)
  721.                         reply[i++] = *c;
  722.                 reply[i] = '\0';
  723.                 return reply;
  724.         }
  725.  
  726.         if ((c = (char *) strchr(line, '<')) != NULL ) {
  727.                 c++;
  728.                 for (i = 0; *c && *c != '>' && *c != '\n' && i < MSGDSTRLEN;
  729.                 c++) {
  730.                         if (*c == '\\')
  731.                                 continue;
  732.                         reply[i++] = *c;
  733.                 }
  734.                 reply[i] = '\0';
  735.                 return reply;
  736.         }
  737.  
  738.         if ((c = (char *) strstr(line, "sage of ")) != NULL) {
  739.                 c += 8;
  740.                 if (*c == '\"')
  741.                         c++;
  742.                 for (i = 0; *c && *c != '.' && *c != '\n' && *c != 'f' &&
  743.                 i < REPYSTRLEN; c++)
  744.                         reply[i++] = *c;
  745.                 reply[i] = '\0';
  746.                 if (*c == 'f')
  747.                         reply[--i] = '\0';
  748.                 return reply;
  749.         }
  750.  
  751.         reply[0] = '\0';
  752.         return reply;
  753. }
  754.